#include "TDAClienteCorreo.h"
#include "TDACorreo.h"
#include "TDAServidorInseguro.h"

#include <time.h>
#include <stdlib.h>
#include <string.h>

/* Cantidad de caracteres del alfabeto. */
#define ALPHABET_QTY 26

/* Definicios para hacer referencia a estados de conexion. */
#define NOT_CONNECTED 0
#define CONNECTED 1

/* Comienzo de funciones auxiliares */

/*
 * Genera una clave aleatoria para usar en la encriptacion
 *
 * Parametros:
 * clave	un char* que apunta a un buffer donde se copiara la clave generada
 *
 * Valor de retorno:
 * N/A
 *
 * PRE: clave apunta a una zona de memoria valida con espacio suficiente para contener MAX_KEY_LEN caracteres y ademas el caracter terminador de cadena
 * POST: se ha generado clave para encriptacion y se la ha copiado en clave
 *
 */
void generarClaveRandom(char* clave);

/* Fin de funciones auxiliares */

void crearClienteCorreo(TDAClienteCorreo* clienteCorreo, char* direcUsr) {

    char clave[MAX_KEY_LEN];

    strcpy(clienteCorreo->direccion,direcUsr);

    generarClaveRandom(clave);
    strcpy(clienteCorreo->clave,clave);
}

void destruirClienteCorreo(TDAClienteCorreo* clienteCorreo) {

    clienteCorreo->servidor = NULL;
	clienteCorreo->estadoConexion = NOT_CONNECTED;

}

void getDirecUsr(TDAClienteCorreo clienteCorreo, char* direcUsr) {
	strcpy(direcUsr, clienteCorreo.direccion);
}

void enviarClave(TDAClienteCorreo clienteCorreo, TDACanalSeguro* canalSeguro) {
    setContenido(canalSeguro, clienteCorreo.clave);
}

void obtenerClave(TDAClienteCorreo* clienteCorreo, TDACanalSeguro canalSeguro) {
    getContenido(canalSeguro, clienteCorreo->clave);
}

void regenerarClave(TDAClienteCorreo* clienteCorreo) {
    char clave[MAX_KEY_LEN];

    generarClaveRandom(clave);
    strcpy(clienteCorreo->clave,clave);
}

int conectar(TDAClienteCorreo* clienteCorreo, TDAServidorInseguro* servidorInseguro) {

	clienteCorreo->servidor = servidorInseguro;
	clienteCorreo->estadoConexion = CONNECTED;

	return 0;
}

int estaConectado(TDAClienteCorreo clienteCorreo) {

	if ( clienteCorreo.estadoConexion ) return CONNECTED;
	return NOT_CONNECTED;
}

void desconectar(TDAClienteCorreo* clienteCorreo) {
    clienteCorreo->estadoConexion = NOT_CONNECTED;
}

int enviarCorreo(TDAClienteCorreo clienteCorreo, TDACorreo correo) {

    /* Simplemente para facilitar la sintaxis al acceder a los         *
     * elementos del servidor.
     */
    TDAServidorInseguro *aux;

    /* Defino una variable auxiliar para el campos del correo, si bien *
     * puedo acceder directamente con "correo.<attr>" es recomendable  *
     * no tener interaccion directa con el correo y valerse de los     *
     * getterS correspondientes.
     */
    char cuerpo[MAX_BODY_SIZE];
    int estado;


    aux = clienteCorreo.servidor;

    getTextoCuerpo(correo, cuerpo);

    encriptarVignere(cuerpo, clienteCorreo.clave, cuerpo);

    setTextoCuerpo( &correo, cuerpo);
    setRemitente(&correo, clienteCorreo.direccion);

    estado = agregarCorreo(aux, correo);

 	return estado;
}

int recibirProximoCorreo(TDAClienteCorreo clienteCorreo, TDACorreo* correo) {

	TDAServidorInseguro *aux;

    aux = clienteCorreo.servidor;

    logmacro("\nRecibiendo correo/s de la cuenta: %s\n",clienteCorreo.direccion);

    /* Chequeo que se hayan descargado mensajes */
/*
    if ( !(obtenerProximoCorreo(aux,clienteCorreo.direccion,correo)) ){

        logmacro("\n\nTexto a desencriptar: %s \nClave a Usar: %s\n",(aux->correo).cuerpo,clienteCorreo.clave);
        desencriptarVignere((aux->correo).cuerpo,clienteCorreo.clave,correo->cuerpo);
        logmacro("\nTexto Desencriptado: %s \n\n",correo->cuerpo);

        return 0;
    }else{
        logmacro("El mensaje no se encuentra dirigido a: %s\n",clienteCorreo.direccion);
        return NO_MESSAGES;
    }
*/
}

void generarClaveRandom(char* clave){

    size_t i=0;
    int keyLen;

    /* Seteo la semilla en un valor random */
    srand((unsigned)time(NULL));

    /* Hago que la longitud de la clave sea random entre 1 y 31 */
    keyLen = (( rand() % (MAX_KEY_LEN - 1) ) + 1);

    /* Re-Seteo la semilla en un valor random */
    srand((unsigned)time(NULL));

    for( ; i<=keyLen ; i++)
        clave[i] = ( ( rand() % ALPHABET_QTY ) + 65 );

    /* Agrego \0 al final para convertirlo en un string valido */
    clave[i] = '\0';

}

int obtenerTodos(TDAClienteCorreo cliente, TListaOrdenada* correos){
    return EXIT_SUCCESS;
}

